package com.faith.dynamic.enums;

import com.faith.dynamic.annotation.FaithSchedule;
import com.faith.dynamic.exception.FaithSysException;
import com.faith.dynamic.model.AddForDynamicDto;
import com.faith.dynamic.model.CancelForDynamicDto;
import com.faith.dynamic.model.UpdateForDynamicDto;
import com.faith.dynamic.task.DynamicScheduledTask;
import com.faith.dynamic.util.FaithDateUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;

/**
 * @ClassName DynamicOperationType$
 * @Description 定时任务操作类型
 * @Author faith$
 * @Date 2019/8/12 14:01
 * @Version 1.0
 **/
@Slf4j
public enum DynamicOperationType implements OperationType {

    LIST() {
        @Override
        public List<String> handle(JoinPoint joinPoint,FaithSchedule faithSchedule) {
            try {
                List<String> tasks = dynamicScheduledTask.getTasks();
                return tasks;
            }catch (Exception e){
                FaithSysException.throwFaithSysException(FaithSysExceptionEnum.QUERY_TASK_LIST_ERROR,e.toString());
            }
            return new ArrayList<>();
        }
    },

    ADD(){
        @Override
        public List<String> handle(JoinPoint joinPoint, FaithSchedule faithSchedule){
            String name = faithSchedule.scheduleMethod();

            try {
                Object[] args = getArgs(joinPoint,name);
                AddForDynamicDto arg = (AddForDynamicDto)args[0];
                // invoke
                String runTime = arg.getRunTime();
                String cronTime = runTime.replaceAll(":", "-").replaceAll(" ", "-");
                String[] date = cronTime.split("-");
                String cron = FaithDateUtil.getCron(date);
                String taskid = UUID.randomUUID().toString().replaceAll("-", "");
                dynamicScheduledTask.addTask(cronTime,cron, taskid);
            } catch (Exception e) {
                FaithSysException.throwFaithSysException(FaithSysExceptionEnum.ADD_TASK_ERROR,e.toString());
                return null;
            }
            return new ArrayList<>();
        }
    },
    UPDATE() {
        @Override
        public List<String> handle(JoinPoint joinPoint,FaithSchedule faithSchedule){
            String name = faithSchedule.scheduleMethod();
            try {
                Object[] args = getArgs(joinPoint,name);
                UpdateForDynamicDto arg = (UpdateForDynamicDto)args[0];
                String cronTime = arg.getRunTime().replaceAll(":", "-").replaceAll(" ", "-");
                String cron = FaithDateUtil.getCron(cronTime.split("-"));
                dynamicScheduledTask.resetTask(cronTime, arg.getTaskId(), cron);
            }catch (Exception e){
                FaithSysException.throwFaithSysException(FaithSysExceptionEnum.ADD_TASK_ERROR,e.toString());
            }
            return new ArrayList<>();
        }
    },
    CANCEL() {
        @Override
        public List<String> handle(JoinPoint joinPoint,FaithSchedule faithSchedule){

            String name = faithSchedule.scheduleMethod();
            try {
                Object[] args = getArgs(joinPoint,name);

                CancelForDynamicDto arg = (CancelForDynamicDto)args[0];
                // invoke
                Object res = null;
                String taskId = arg.getTaskId();
                boolean resetTask = dynamicScheduledTask.cancelTask(taskId);
            }catch (Exception e){
                FaithSysException.throwFaithSysException(FaithSysExceptionEnum.CANCEL_TASK_ERROR,e.toString());
            }
            return new ArrayList<>();
        }
    };
    public DynamicScheduledTask dynamicScheduledTask;
    public DynamicScheduledTask getDynamicScheduledTask(){
        return dynamicScheduledTask;
    }
    public void setDynamicScheduledTask(DynamicScheduledTask dynamicScheduledTask){
        this.dynamicScheduledTask = dynamicScheduledTask;
    }
    @Component
    public static class DynamicScheduleServiceInjector{
        @Autowired
        private DynamicScheduledTask dynamicScheduledTask;
        @PostConstruct
        public void postConstruct(){
            for(DynamicOperationType type: EnumSet.allOf(DynamicOperationType.class)){
                type.setDynamicScheduledTask(dynamicScheduledTask);
            }
        }
    }
    private static Object[] getArgs(JoinPoint joinPoint,String name) throws Exception{
        Object res = null;
        Method currentMethod = ((MethodSignature)joinPoint.getSignature()).getMethod();
        Object target = joinPoint.getTarget();
        Method handleMethod = joinPoint.getTarget().getClass().getDeclaredMethod(name, currentMethod.getParameterTypes());
        handleMethod.setAccessible(true);
        Object[] args = joinPoint.getArgs();
        res = handleMethod.invoke(target, args);
        return args;
    }
}
